#pragma once
#include<atomic>
#include"Channel.h"
#include"Callback.h"
namespace wjc {

	class TimerChannel :public std::enable_shared_from_this<TimerChannel> {
	private:
		Core* core_;
		int timerfd_;
		std::shared_ptr<Channel> channel_;
		int interval_ms_;

		std::atomic_bool start_;
		
		OnTimerCallback onTimer_;

		void startInCore() {
			channel_->enableReading();
			resetTimerfd(timerfd_, interval_ms_);
		}

		void cancelInCore() {
			channel_->disableAll();
			resetTimerfd(timerfd_, 0);
		}

		void handleRead();

		int createTimerfd();

		void resetTimerfd(int timerfd, int64_t interval_ms);

	public:
		TimerChannel(Core* core, int64_t interval_ms);
		~TimerChannel();

		void setOnTimerCallback(OnTimerCallback onTimer) {
			onTimer_ = std::move(onTimer);
		}

		void start() {
			bool excepted = false;
			if (start_.compare_exchange_strong(excepted, true)) {
				core_->runInCore(CreateTask(std::bind(&TimerChannel::startInCore, shared_from_this())));
			}
		}

		void cancel() {
			bool excepted = true;
			if (start_.compare_exchange_strong(excepted, false)) {
				core_->runInCore(CreateTask(std::bind(&TimerChannel::cancelInCore, shared_from_this())));
			}
		}

		void destruction() {

			auto guard = shared_from_this();
			if (core_->isInCoreThread()) {
				cancelInCore();
				channel_->disableAll();
				channel_->remove();
			}
			else {
				core_->runInCore(CreateTask(std::bind(&TimerChannel::destruction, guard)));
			}
		}
	};
}
